﻿using dnAnalytics.LinearAlgebra;
using dnAnalytics.LinearAlgebra.Solvers.Direct;
using NUnit.Framework;

namespace dnAnalytics.Tests.LinearAlgebra.Solvers.Direct
{
    public abstract class CholeskySolverTests
    {
        private const string matrixFile = "./TestData/Matrices/hilbert_real_symmetric_array_10.mtx";

        protected abstract Matrix GetMatrix(string file);
        protected abstract Matrix GetIdentityMatrix(int size);
        protected abstract Vector GetVector(int count);

        [Test]
        public void SolveMatrix()
        {
            Matrix matrix = GetMatrix(matrixFile);
            Matrix identity = GetIdentityMatrix(matrix.Rows);
            CholeskySolver solver = new CholeskySolver();
            Matrix result = solver.Solve(matrix, identity);
            result = matrix*result;

            for (int i = 0; i < result.Rows; i++)
            {
                for (int j = 0; j < result.Columns; j++)
                {
                    if (i == j)
                    {
                        Assert.AreEqual(1, result[i, j], Constants.AcceptableCholeskySolveError);
                    }
                    else
                    {
                        Assert.AreEqual(0, result[i, j], Constants.AcceptableCholeskySolveError);
                    }
                }
            }
        }

        [Test]
        public void SolveVector()
        {
            Matrix matrix = GetMatrix(matrixFile);
            Vector vector = GetVector(matrix.Rows);
            for (int i = 0; i < vector.Count; i++)
            {
                vector[i] = (double) (i + 1)/(i + 2);
            }
            CholeskySolver solver = new CholeskySolver();
            Vector result = solver.Solve(matrix, vector);
            Vector resultVector = matrix*result;
            for (int i = 0; i < resultVector.Count; i++)
            {
                Assert.AreEqual((double) (i + 1)/(i + 2), resultVector[i], Constants.AcceptableCholeskySolveError);
            }
        }
    }
}